package com.control.back.halo.bookmark.parse;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.NodeTraversor;
import org.jsoup.select.NodeVisitor;

import com.control.back.halo.basic.log4j.Logger;

public class Html2Article {

    private static Logger LOGGER = Logger.getLogger(Html2Article.class);

    public static String getContent(String bodyText) {

        String[] orgLines = null; // 保存原始内容，按行存储
        String[] lines = null; // 保存干净的文本内容，不包含标签

        orgLines = bodyText.split("\n");
        lines = new String[orgLines.length];
        // 去除每行的空白字符,剔除标签
        for (int i = 0; i < orgLines.length; i++) {
            String lineInfo = orgLines[i];
            // 处理回车，使用[crlf]做为回车标记符，最后统一处理
            lineInfo = lineInfo.replaceAll("\n", "[crlf]");
            lines[i] = lineInfo.trim();
        }

        StringBuilder sb = new StringBuilder();

        int preTextLen = 0; // 记录上一次统计的字符数量（lines就是去除html标签后的文本，_limitCount是阈值，_depth是我们要分析的深度，sb用于记录正文）
        int startPos = -1; // 记录文章正文的起始位置
        int _depth = 6; // 按行分析的深度，默认为6
        int _headEmptyLines = 2; // 确定文章正文头部时，向上查找，连续的空行到达_headEmptyLines，则停止查找
        int _limitCount = 180; /// 字符限定数，当分析的文本数量达到限定数则认为进入正文内容
                               /// 默认180个字符数
        int _endLimitCharCount = 20; // 用于确定文章结束的字符数
        boolean appendMode = false;
        for (int i = 0; i < lines.length - _depth; i++) {
            int len = 0;
            for (int j = 0; j < _depth; j++) {
                len += lines[i + j].length();
            }

            if (startPos == -1) // 还没有找到文章起始位置，需要判断起始位置
            {
                if (preTextLen > _limitCount && len > 0) // 如果上次查找的文本数量超过了限定字数，且当前行数字符数不为0，则认为是开始位置
                {
                    // 查找文章起始位置, 如果向上查找，发现2行连续的空行则认为是头部
                    int emptyCount = 0;
                    for (int j = i - 1; j > 0; j--) {
                        if (lines[j] == null || lines[j].trim().equals("")) {
                            emptyCount++;
                        } else {
                            emptyCount = 0;
                        }
                        if (emptyCount == _headEmptyLines) {
                            startPos = j + _headEmptyLines;
                            break;
                        }
                    }
                    // 如果没有定位到文章头，则以当前查找位置作为文章头
                    if (startPos == -1) {
                        startPos = i;
                    }
                    // 填充发现的文章起始部分
                    for (int j = startPos; j <= i; j++) {
                        sb.append(lines[j]);
                    }
                }
            } else {
                if (len <= _endLimitCharCount && preTextLen < _endLimitCharCount) // 当前长度为0，且上一个长度也为0，则认为已经结束
                {
                    if (!appendMode) {
                        break;
                    }
                    startPos = -1;
                }
                sb.append(lines[i]);
            }
            preTextLen = len;
        }

        return sb.toString();
    }

    public static String bodyText(Element body) {
        final StringBuilder accum = new StringBuilder();
        new NodeTraversor(new NodeVisitor() {
            public void head(Node node, int depth) {
                if (node instanceof TextNode) {
                    TextNode textNode = (TextNode) node;
                    String text = textNode.getWholeText();
                    accum.append(text);
                }
            }

            public void tail(Node node, int depth) {
            }
        }).traverse(body);
        return accum.toString();
    }

    public static String getContentByUrl(String url) {
        LOGGER.warn("url:%s", url);
        try {
            Document doc = Jsoup.connect(url).userAgent("Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0").ignoreContentType(true).timeout(30000).get();
            return Html2Article.getContent(bodyText(doc.body()));
        } catch (Exception e) {
            LOGGER.error("getContentByUrl exception :", e);
        }
        return null;
    }
}
